// memerror.m -- try to find (and fix!) all the memory-related errors in
// this program
// Take a string from the command line. Make a linked-list out of it in
// reverse order. Traverse it to construct a string in reverse. Then clean
// up afterwards.
// gcc -w -g -o memerror memerror.m

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct CharNode {
char theChar;
struct CharNode *next;
} CharNode;

// Build a linked list backwards, then walk the list.

void reverseIt (char *stringbuffer) {
    CharNode *head, *node;
    char *scan, *stop;
    // Clear out local vars
    head = node = NULL;
    // Find the start and end of the string so we can walk it
    scan = stringbuffer;
    stop = stringbuffer + strlen(stringbuffer); // trailing null
    // Walk the string
    while (scan < stop) {
        if (head == NULL) {
            head = malloc (sizeof(CharNode));
            head->theChar = *scan;
            head->next = NULL;
        } else {
            node = malloc (sizeof(CharNode));
            node->theChar = *scan;
            node->next = head;
            head = node;
        }
        scan++;
    }
    // Ok, re-point to the buffer so we can drop the characters
    scan = stringbuffer;
    // Walk the nodes and add them to the string
    while (head != NULL) {
        *scan = head->theChar;
        node = head->next;
        head = node;
        free (head);
	scan++;
    }
    // Clean up the head
    free (head);
} // reverseIt

int main (int argc, char *argv[]) {
    char *stringbuffer;
    // Make sure the user supplied enough arguments. If not, complain.
    if (argc != 2) {
        fprintf (stderr, "usage: %s string. This reverses the string "
                 "given on the command line\n", argv[0]);
        return 1;
    }
    // Make a copy of the argument so we can make changes to it.
    stringbuffer = malloc (strlen(argv[1]));
    strcpy (stringbuffer, argv[1]);
    // reverse the string
    reverseIt (stringbuffer);
    // and print it out
    printf ("the reversed string is '%s'\n", stringbuffer);
    return 0;
} // main
